package com.ruoyi.qd.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.validate.ValidatorUtil;
import com.ruoyi.qd.domain.TradeWater;
import com.ruoyi.qd.vo.TradeWaterAddReq;
import com.ruoyi.qd.vo.TradeWaterPageH5Req;
import com.ruoyi.qd.vo.TradeWaterPageH5Res;
import com.ruoyi.qd.vo.TradeWaterPageReq;
import com.ruoyi.qd.vo.TradeWaterPageRes;
import com.ruoyi.qd.enums.TradeWaterTypeEnum;
import com.ruoyi.qd.mapper.TradeWaterMapper;
import com.ruoyi.qd.service.ITradeWaterService;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import static com.ruoyi.common.core.domain.entity.table.SysUserTableDef.SYS_USER;
import static com.ruoyi.qd.domain.table.TradeWaterTableDef.TRADE_WATER;

/**
 * 交易流水Service业务层处理
 *
 * @author tushiguang
 * @date 2024-07-24
 */
@Service
public class TradeWaterServiceImpl extends ServiceImpl<TradeWaterMapper, TradeWater> implements ITradeWaterService {
    @Override
    public BigDecimal calculateBalance(Long userId) {
        if (Objects.isNull(userId)) {
            throw new ServiceException("用户id不能为空");
        }

        List<TradeWater> tradeWaterList = TradeWater.create()
                .select(TradeWater::getMoney, TradeWater::getType)
                .where(TradeWater::getUserId).eq(userId)
                .list();

        BigDecimal balance = BigDecimal.ZERO;
        for (TradeWater tradeWater : tradeWaterList) {
            if (TradeWaterTypeEnum.POSITIVE_CODE_LIST.contains(tradeWater.getType())) {
                balance = balance.add(tradeWater.getMoney());
            } else {
                balance = balance.subtract(tradeWater.getMoney());
            }
        }
        return balance;
    }

    @Override
    public void add(TradeWaterAddReq tradeWaterAddReq) {
        ValidatorUtil.validateEntity(tradeWaterAddReq);

        TradeWater.create()
                .setUserId(tradeWaterAddReq.getUserId())
                .setMoney(tradeWaterAddReq.getAmount())
                .setType(tradeWaterAddReq.getType())
                .saveOpt()
                .orElseThrow(() -> new ServiceException("交易流水添加失败"));
    }

    /**
     * 查询交易流水
     *
     * @param id 交易流水主键
     * @return 交易流水
     */
    @Override
    public TradeWater selectTradeWaterById(Long id) {
        return mapper.selectOneById(id);
    }

    @Override
    public Page<TradeWaterPageH5Res> selectTradeWaterPageH5(
            PageDomain pageDomain, TradeWaterPageH5Req tradeWaterPageH5Req) {
        Page<TradeWaterPageH5Res> tradeWaterPageH5ResPage = TradeWater.create()
                .where(TRADE_WATER.USER_ID.eq(tradeWaterPageH5Req.getUserId()))
                .orderBy(TRADE_WATER.ID.desc())
                .pageAs(new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize()), TradeWaterPageH5Res.class);
        tradeWaterPageH5ResPage.getRecords()
                .forEach(tradeWaterPageH5Res -> {
                    tradeWaterPageH5Res.setTypeStr(TradeWaterTypeEnum.getInfoByCode(tradeWaterPageH5Res.getType()));
                    if (TradeWaterTypeEnum.POSITIVE_CODE_LIST.contains(tradeWaterPageH5Res.getType())) {
                        tradeWaterPageH5Res.setMoneyStr("+" + NumberUtil.decimalFormat("#.##", tradeWaterPageH5Res.getMoney()));
                        tradeWaterPageH5Res.setThumb("/static/images/purse/income.png");
                    } else {
                        tradeWaterPageH5Res.setMoneyStr("-" + NumberUtil.decimalFormat("#.##", tradeWaterPageH5Res.getMoney()));
                        tradeWaterPageH5Res.setThumb("/static/images/purse/expenditure.png");
                    }
                });
        return tradeWaterPageH5ResPage;
    }

    @Override
    public Page<TradeWaterPageRes> selectTradeWaterPage(PageDomain pageDomain, TradeWaterPageReq tradeWaterPageReq) {
        return TradeWater.create()
                .select(TRADE_WATER.ALL_COLUMNS, SYS_USER.USER_NAME)
                .leftJoin(SYS_USER).on(SYS_USER.USER_ID.eq(TRADE_WATER.USER_ID))
                .where(SYS_USER.USER_NAME.eq(tradeWaterPageReq.getUsername()))
                .and(TRADE_WATER.TYPE.eq(tradeWaterPageReq.getType()))
                .orderBy(TRADE_WATER.ID.desc())
                .pageAs(new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize()), TradeWaterPageRes.class);
    }

    /**
     * 查询交易流水列表
     *
     * @param tradeWater 交易流水
     * @return 交易流水
     */
    @Override
    public List<TradeWater> selectTradeWaterList(TradeWater tradeWater) {
        QueryWrapper query = buildWrapper(tradeWater);
        return mapper.selectListByQuery(query);
    }

    public QueryWrapper buildWrapper(TradeWater tradeWater) {
        return query()
                .where(TRADE_WATER.USER_ID.eq(tradeWater.getUserId()))
                .and(TRADE_WATER.TYPE.eq(tradeWater.getType()));
    }

    /**
     * 修改交易流水
     *
     * @param tradeWater 交易流水
     * @return 结果
     */
    @Override
    public int updateTradeWater(TradeWater tradeWater) {
        return mapper.update(tradeWater);
    }

    /**
     * 批量删除交易流水
     *
     * @param ids 需要删除的交易流水主键
     * @return 结果
     */
    @Override
    public int deleteTradeWaterByIds(Long[] ids) {
        return mapper.deleteBatchByIds(Arrays.asList(ids));
    }

    /**
     * 删除交易流水信息
     *
     * @param id 交易流水主键
     * @return 结果
     */
    @Override
    public int deleteTradeWaterById(Long id) {
        return mapper.deleteById(id);
    }
}
